local Lang = require("common.Lang")
local ExcelMap = require("excel.Map")
local CopyConfig = ExcelMap.copy
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local CopyDefine = require("copy.Define")
local Copy = require("copy.CopyL")
local CopyTeam = require("copy.CopyTeam")
local CopyFamily = require("copy.CopyFamily")
local CopyAim = require("copy.Aim")
local CopyReward = require("copy.CopyReward")
local Broadcast = require("broadcast.Broadcast")
local Grid = require("bag.Grid")
local ItemDefine = require("bag.ItemDefine")
--local Util = require("common.Util")
local RoleFFI = require("role.RoleFFI")
local Pata  = require("copy.Pata")
local CopyCommon = require("copy.CopyCommon")
local RetRewardItem = {}
local RewardItemGridCache = {}		-- 副本奖励道具grid缓存 避免频繁new grid
local ConditionItemGridCache = {}	-- 副本条件道具grid缓存 避免频繁new grid
local Wushuang = require("copy.Wushuang")
local Aim = require("copy.Aim")
local CopyCallback = require("copy.CallbackL")
local JZWar = require("copy.JZWar")
local FamilyWar = require("copy.FamilyWar")
local TaskDuanceng = require("task.Duanceng")
local HorseFight = require("copy.HorseFight")
local DHFight = require("copy.DHFight")

function copyEnter(human, copyID, noCheckCopy, startTime)
    -- 这里对大汉格斗场进行特殊处理，因为玩家进入该副本后要按照实际所在的副本与层数来进入地图
    local copyID = CopyCommon.specialCtl(human, copyID) 
    print("copyID:", copyID)

    local err  = CopyCommon.checkEnterCondition(human, copyID, noCheckCopy)
    if err then
        Broadcast.sendBroadcast(human, Lang.DOWN, err)
        return
    end		

    if not CopyCallback.onCheckEnterCondition(human, copyID) then --各个副本特殊检查条件       
        return
    end
    if Copy.checkCrossCopyRoom(human, copyID, startTime) then
        return true	
    end
    -- 申请副本房间
    local roomID = Copy.applyCopyRoom(copyID, human._id, startTime)
    if roomID == nil then
        Broadcast.sendBroadcast(human, Lang.DOWN, Lang.COPY_ENTER_ERR_COPY_FULL)

        return	
    end
    Copy.humanBeginCopy(human, copyID, roomID, nil, nil)	
    return true
end

function CG_COPY_ENTER(human,m)
    local copyID = m.copyID
    local cf = CopyConfig[copyID]
    if not cf then
        return
    end
    copyEnter(human, copyID)
end


function CG_COPY_LEAVE(human)
    local sceneID = human.scene_id
    local copyID = Copy.sceneID2CopyID[sceneID]
    if not copyID then
        return 
    end

    local roomID = Copy.sceneID2Room[sceneID]
    if Copy.roomDatas[copyID][roomID].finishCode then
        if CopyReward.sendCopyRewardNotify(human, copyID) == nil then
            -- 如果副本状态是已完成 那么下发通关奖励提示
            Copy.humanEndCopy(human, copyID, roomID)
        end
    else
        Copy.humanEndCopy(human, copyID, roomID)
    end
end
function CG_COPY_AIM_ACCEPT(human, msg)
    onCopyAimAccept(human,msg.aimID)
end

function onCopyAimAccept(human,aimID)
    local sceneID = human.scene_id
    local copyID = Copy.sceneID2CopyID[sceneID]
    local roomID = Copy.copyHuman2Room[human._id]

    if copyID == nil or roomID == nil then return end

    local ret = CopyAim.aimCanAccept(aimID, copyID, roomID)
    if ret == CopyDefine.COPY_AIM_ACCEPT_OK then
        CopyAim.aimDoAccept(aimID, copyID, roomID)
        return
    end
    Broadcast.sendBroadcast(human, Lang.DOWN, CopyDefine.errAcceptTip[ret])
end

function CG_COPY_AIM_FINISH(human, msg)
    local sceneID = human.scene_id
    local copyID = Copy.sceneID2CopyID[sceneID]
    local roomID = Copy.copyHuman2Room[human._id]

    if copyID == nil or roomID == nil then return end

    local ret = CopyAim.aimCanFinish(msg.aimID, copyID, roomID, human) 
    if ret == CopyDefine.COPY_AIM_FINISH_OK then
        CopyAim.aimDoFinish(msg.aimID, copyID, roomID)
        return
    end

    Broadcast.sendBroadcast(human, Lang.DOWN, CopyDefine.errFinishTip[ret])
end



function addVipCopyCnt(human, copyID)
    local config = CopyConfig[copyID]
    copyID = config.group
    for i = 0, human.db.copyTimesLen-1 do
        if human.db.copyTimes[i].copy_id == copyID then
            human.db.copyTimes[i].addCnt = human.db.copyTimes[i].addCnt + 1
            TaskDuanceng.onCopyCntChange(human)
            return
        end
    end
    human.db.copyTimes[human.db.copyTimesLen].copy_id = copyID
    human.db.copyTimes[human.db.copyTimesLen].times = 0
    human.db.copyTimes[human.db.copyTimesLen].addCnt = 1
    human.db.copyTimesLen  = human.db.copyTimesLen + 1
    TaskDuanceng.onCopyCntChange(human)
    
    if human.db.copyTimesLen  >= 100 then
        assert()
    end
    return 0
end

function incCopyEnterCount(human, copyID, cnt)
    if cnt == nil then cnt = 1 end
    local config = CopyConfig[copyID]
    copyID = config.group
    for i = 0, human.db.copyTimesLen-1 do
        if human.db.copyTimes[i].copy_id == copyID then
            human.db.copyTimes[i].times = human.db.copyTimes[i].times + cnt
            TaskDuanceng.onCopyCntChange(human)
            return
        end
    end

    human.db.copyTimesLen  = human.db.copyTimesLen + 1
    human.db.copyTimes[human.db.copyTimesLen-1].copy_id = copyID
    human.db.copyTimes[human.db.copyTimesLen-1].times =  cnt
    human.db.copyTimes[human.db.copyTimesLen-1].addCnt = 0
    if human.db.copyTimesLen  >= 100 then
        assert()
    end
    TaskDuanceng.onCopyCntChange(human)
end

function getRewardItem(copyID, copyConfig)
    RewardItemGridCache[copyID] = RewardItemGridCache[copyID] or {}
    copyConfig = copyConfig or CopyConfig[copyID]
    local count = 0	
    for i = 1, #copyConfig.reward do
        local itemID = copyConfig.reward[i][1]
        local itemCount = copyConfig.reward[i][2]
        local itemQuality = copyConfig.reward[i][3]
        if RewardItemGridCache[copyID][itemID] == nil then
            RewardItemGridCache[copyID][itemID] = {}
            Grid.create(RewardItemGridCache[copyID][itemID],itemID, itemCount, nil, ItemDefine.getQualityOut(itemQuality))
        end
        count = count + 1
        RetRewardItem[count] = RewardItemGridCache[copyID][itemID]
    end
    return count, RetRewardItem
end

function getConditionItem(itemID)
    if ConditionItemGridCache[itemID] == nil then 
        ConditionItemGridCache[itemID] = Grid.create(itemID, 1, nil)
    end
    return ConditionItemGridCache[itemID]
end



function CG_COPY_REWARD_GET(human, msg)
    local sceneID = human.scene_id
    local copyID = Copy.sceneID2CopyID[sceneID]
    if not copyID or copyID ~= msg.copyID then
        return 
    end

    local roomID = Copy.sceneID2Room[sceneID]

    local msgRet = Msg.gc.GC_COPY_REWARD_GET
    msgRet.copyID = copyID
    msgRet.retCode = 0
    Msg.send(msgRet, human.fd)

    Copy.humanEndCopy(human, msg.copyID, roomID)
end



--向副本所在线程申请房间
function WL_CROSS_ROOM_APPLY(uuid, msg)
    local roomID = Copy.applyCopyRoom(msg.copyid, msg.uuid, msg.startTime)
    if roomID == nil then
        roomID = 0
    end
    local mm = Msg.lw.LW_CROSS_ROOM_APPLY_RESULT
    mm.copyid = msg.copyid
    mm.roomid = roomID
    mm.uuid = msg.uuid
    Msg.send2world(mm, "")  
    print("WL_CROSS_ROOM_APPLY:".."  ".._G.logic_id)
end


--收到申请房间结果
function WL_CROSS_ROOM_APPLY_RESULT(human, msg)
    if msg.roomid == 0 then
        Broadcast.sendBroadcast(human, Lang.DOWN, Lang.COPY_ENTER_ERR_COPY_FULL)
        return
    end
    if Copy.getCopyLogicID(msg.copyid) ~= _G.logic_id then
        if human.fd == nil then  --已断线的情况，不要再跑下面了。
            return
        end
        human.db.copyEnterMap = human.db.map_id --这里需要设置下copyEnterMap,以便找不到时退出到原地图  
        human.db.copyEnterX = human.db.x 
        human.db.copyEnterY = human.db.y 
        local enterMsg = Msg.lw.LW_CROSS_COPY_ROOM_ENTER
        enterMsg.copyid = msg.copyid
        enterMsg.roomid = msg.roomid
        ObjHuman.destroy(human)      --干掉本线程的，
        Msg.send2world(enterMsg, human._id)
    else    
        if Copy.roomDatas[msg.copyid][msg.roomid] and Copy.roomDatas[msg.copyid][msg.roomid].finishCode == nil then
            Copy.humanBeginCopy(human, msg.copyid, msg.roomid)  
        elseif Copy.roomDatas[msg.copyid][msg.roomid]  and Copy.roomDatas[msg.copyid][msg.roomid].finishCode then
            if CopyConfig[msg.copyid].type == CopyDefine.COPY_TYPE_TEAM then -- 组队副本队友进入时 副本可能已经结束
                Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.COPY_TEAM_INVITE_CANNOT_ENTER_FINISH)
            end
        end
    end
end
function WL_CROSS_COPY_ROOM_ENTER(uuid, msg)
    if type(uuid) ~= "string" then
        assert()
    end
    local fd = msg.fd
    local db = RoleFFI.find_ffi_by_fd(fd)
    local human = ObjHuman.create(fd, RoleFFI.ffi_string(db.account),db, msg.id, msg.uid)  
    if Copy.roomDatas[msg.copyid][msg.roomid] == nil or Copy.roomDatas[msg.copyid][msg.roomid].finishCode ~= nil then 
        local backHomeMapId, backHomeX, backHomeY = Copy.getBackHomePoint(human, msg.copyid)
        ObjHuman.enterMap(human, backHomeMapId, backHomeX, backHomeY)  -- 副本已经结束,回去
        return
    end
    human.isLogin = msg.login == 1 and true or nil
    Copy.humanBeginCopy(human, msg.copyid, msg.roomid)  
end

function WL_COPY_TEAM_CB(uuid, msg)
    local fun = CopyTeam[msg.type]
    if fun then
        fun(msg.uuid,msg.copyID, msg.roomID)
    end
end

function WL_COPY_FAMILY_CB(uuid, msg)
    local fun = CopyFamily[msg.type]
    if fun then
        fun(msg.uuid, msg.copyID, msg.roomID)
    end
end


-- 队友进入
function CG_COPY_TEAM_INVITE_ENTER(human, msg)
    local copyID = msg.copyID
    local copyConfig = CopyConfig[copyID]
    if copyConfig.type ~= CopyDefine.COPY_TYPE_TEAM then return end
    if msg.type < 0 or msg.type > 1 then 
        return
    end
    if human.db.teamUuidLen < 1 then
        return
    end   
    if msg.type == 0 then
        CopyTeam.sendTeamError(human, msg.copyID, string.format(Lang.COPY_TEAM_INVITE_REJECT_MSG, human.name))
        return 
    end
    copyEnter(human, copyID)
end

--爬塔相关
function CG_COPY_PATA_QUERY(human, msg)
    Pata.query(human, msg.sendReward)
end
function CG_COPY_PATA_FIRST_QUERY(human)
    Pata.query_first(human)
end
function CG_COPY_PATA_FIRST_GET(human, msg)
    Pata.first_get(human, msg.guan)
end
function CG_COPY_PATA_ENTER(human)
    local tempSec = ObjHuman.checkFightSec(human,20)
    if tempSec>0  then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.COPY_PATA_FIGHT)
        return
    end 
    Pata.copyEnter(human)
end
function CG_COPY_PATA_RESET(human)
    Pata.reset(human)
end
function CG_COPY_PATA_ADD_RESET(human)
    Pata.add_reset(human)
end
function CG_COPY_PATA_KO(human)
    Pata.ko(human)
end
function CG_COPY_PATA_KO_GET(human, msg)
    if msg.type < 1 or msg.type > 2 then
        return
    end
    Pata.ko_reward(human, msg.type)
end

function CG_COPY_PATA_STORE(human)
    Pata.sendStore(human)
end

function CG_COPY_PATA_STORE_GET(human, msg)
    if msg.pos < 0 then
        Pata.getAllStore(human)
    else
        Pata.getStore(human, msg.pos)
    end
end

function CG_COPY_PATA_FIRST_DIE_GET(human)
	Pata.firstDieGet(human)
end

function CG_COPY_WUSHUANG_OPEN(human)
    Wushuang.open(human)
end

function CG_COPY_WUSHUANG_ADD_TIMES(human)
    Wushuang.addTimes(human)
end

function CG_COPY_GET_PLACE(human, msg)
    Aim.aimReachArea(human, msg.aimID)  
end

function CG_JZWAR_FORAGE(human)
    JZWar.onForage(human)
end

function CG_JZWAR_BACK_BLOOD(human)
    JZWar.onBackBlood(human)
end

function CG_COPY_HORSE_FIGHT_END(human)
  HorseFight.enterEndArea(human)
end

XUBAO_COST = nil
function CG_COPY_XUNBAO_QUERY(human)
  local msg = Msg.gc.GC_COPY_XUNBAO_QUERY
  local costItemCnt = Copy.getXunbaoCostCnt(human)
  msg.curCnt = CopyCommon.getCopyEnterCount(human, CopyDefine.COPY_XUNBAO_COPY_ID)
  msg.maxCnt = CopyCommon.getCopyMaxEnterCount(human, CopyDefine.COPY_XUNBAO_COPY_ID)
  
  if XUBAO_COST == nil then
      msg.copyID = CopyDefine.COPY_XUNBAO_COPY_ID
      local copyConfig = CopyConfig[CopyDefine.COPY_XUNBAO_COPY_ID]
      local count,list = getRewardItem(CopyDefine.COPY_XUNBAO_COPY_ID, copyConfig)
      if count > 8 then count = 8 end
      for i = 1, count do
          Grid.makeItem(list[i], msg.reward[i], 0, human)
      end
      msg.reward[0] = count
      XUBAO_COST = {}
      Grid.create(XUBAO_COST, ItemDefine.ITEM_ID_XUBAO_ITEM, costItemCnt ,true)
      Grid.makeItem(XUBAO_COST,msg.costItem, 0, human)
  else
      msg.costItem.cnt = costItemCnt
  end
  Msg.send(msg, human.fd)
end

function CG_FAMILYWAR_ORDER(human, msg)
    FamilyWar.onOrder(human, msg.type)
end

function CG_FAMILYWAR_BACK_BLOOD(human)
    FamilyWar.onBackBlood(human)
end

function CG_DHFIGHT_KINGMSG(human)
    DHFight.onKingMsg(human)
end
